#include "ImageDialog.h"
#include "ImageListBox.h"
#include "ui_ImageSettingsWidget.h"
#include <cassert>
#include <QtGui>
#include <QtXml>

Q_DECLARE_METATYPE(QDomElement)

class ImageSettingsWidget : public QWidget, public Ui::ImageSettingsWidget {
public:
    ImageSettingsWidget(QWidget *parent);
};

ImageSettingsWidget::ImageSettingsWidget(QWidget *parent) : QWidget(parent) {
    setupUi(this);
}

ImageWindow::ImageWindow(QDomElement root, QWidget *parent) : QWidget(parent, Qt::Window|Qt::WindowMinMaxButtonsHint) {
    loadingMessage = true;
    setWindowTitle(tr("Images"));
    setAttribute(Qt::WA_DeleteOnClose);
    this->root = root;
    layout = new QVBoxLayout(this);
    listBox = new ImageListBox(this);
    layout->addWidget(listBox);
    connect(listBox, SIGNAL(clicked(QVariant)), SLOT(selectionChanged(QVariant)));

    QFrame *separator = new QFrame(this);
    separator->setFrameStyle(QFrame::HLine);
    layout->addWidget(separator);

    settingsWidget = new ImageSettingsWidget(this);
    settingsWidget->lblInfo->setText(tr("Loading Thumbnails..."));
    layout->addWidget(settingsWidget);
    connect(settingsWidget->chkEnabled, SIGNAL(clicked(bool)), SLOT(enableToggled()));
    connect(settingsWidget->radDefault, SIGNAL(clicked(bool)), SLOT(radioBtnClicked()));
    connect(settingsWidget->radCenter, SIGNAL(clicked(bool)), SLOT(radioBtnClicked()));
    connect(settingsWidget->radTile, SIGNAL(clicked(bool)), SLOT(radioBtnClicked()));
    connect(settingsWidget->radStretchIgnore, SIGNAL(clicked(bool)), SLOT(radioBtnClicked()));
    connect(settingsWidget->radStretchCrop, SIGNAL(clicked(bool)), SLOT(radioBtnClicked()));
    connect(settingsWidget->radStretchLeave, SIGNAL(clicked(bool)), SLOT(radioBtnClicked()));
    connect(&loadTimer, SIGNAL(timeout()), SLOT(loadTimerEvent()));
    loadTimer.start(2200);
    QTimer::singleShot(0, this, SLOT(lazyLoad()));
}

void ImageWindow::lazyLoad() {
    //size and center the window
    int screen = 0;
    QWidget *w = topLevelWidget();
    QDesktopWidget *desktop = QApplication::desktop();
    if (w) {
        screen = desktop->screenNumber(w);
    } else if (desktop->isVirtualDesktop()) {
        screen = desktop->screenNumber(QCursor::pos());
    } else {
        screen = desktop->screenNumber(this);
    }
    QRect rect(desktop->availableGeometry(screen));
    resize(int(rect.width() * .85), int(rect.height() * .85));
    move(rect.width()/2 - frameGeometry().width()/2,
         rect.height()/2 - frameGeometry().height()/2);
    QTimer::singleShot(0, this, SLOT(loadTimerEvent()));
}

void ImageWindow::loadTimerEvent() {
    QDateTime stopTime = QDateTime::currentDateTime().addSecs(2); //runs for a mininum of x seconds
    int totalImages = 0;
    QDomNodeList list = root.childNodes();
    for (int a=0;a<list.size();++a) {
        QDomNode n = list.at(a);
        QDomElement e = n.toElement();
        if (!e.isNull() && e.tagName() == "image") {
            ++totalImages; 
            if (QFile::exists(e.attribute("file")) && !loadedImages.contains(e.attribute("file"))) {
                loadedImages.append(e.attribute("file"));
                addFile(e);
                if (QDateTime::currentDateTime() > stopTime) return;
            }
        }
    }
    loadTimer.stop();
    if (loadingMessage) {
        loadingMessage = false;
        settingsWidget->lblInfo->setText(tr("%1 total images").arg(totalImages));
    }
}

void ImageWindow::addFile(QDomElement e) {
    QFile file(e.attribute("file"));
    if (!file.open(QIODevice::ReadOnly)) {
        qDebug() << "opening " << e.attribute("file") << "failed: " << file.errorString();
        return;
    }
    QByteArray data = file.readAll();
    file.close();
    QByteArray thumbFile = QByteArray("wp_") + QCryptographicHash::hash(data, QCryptographicHash::Md5).toHex().left(10) + ".jpg";
    QDir::temp().mkdir("wallpaperchanger");
    QString thumbLocation = QDir::tempPath() + "/wallpaperchanger/" + thumbFile;
    bool thumbExists = QFile::exists(thumbLocation);

    ImageIcon *icon = new ImageIcon(listBox);
    QVariant v;
    v.setValue<QDomElement>(e);
    icon->setId(v);
    icon->setImageEnabled(e.attribute("enabled").toInt());

    QPixmap thumb;
    if (thumbExists) {
        thumb = QPixmap(thumbLocation);
    } else {
        QBuffer buffer(&data);
        assert(buffer.size());
        qDebug() << QImageReader::imageFormat(file.fileName());
        buffer.open(QIODevice::ReadOnly);
        QImageReader ir(&buffer, QImageReader::imageFormat(file.fileName()));
        QImage img = ir.read();
        thumb = QPixmap::fromImage(img.scaled(150, 100, Qt::KeepAspectRatio, Qt::SmoothTransformation));
        thumb.save(thumbLocation, "JPG", 75);
        qDebug() << "saved " << thumbLocation;
    }
    icon->setPixmap(thumb);
    listBox->addIcon(icon);
}

void ImageWindow::selectionChanged(QVariant id) {
    selected = id.value<QDomElement>();
    QString file = selected.attribute("file");
    QPixmap pix(file);
    QSize size = pix.size();
    loadingMessage = false;
    settingsWidget->lblInfo->setText(
            tr("%1\n%2x%3")
            .arg(QFileInfo(file).fileName())
            .arg(size.width())
            .arg(size.height()));
    size.scale(settingsWidget->scrImage->width()-40,
            settingsWidget->scrImage->height()-40, Qt::KeepAspectRatio);
    pix = pix.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
    settingsWidget->grpDisplay->setEnabled(true);
    settingsWidget->lblImage->setPixmap(pix);
    QString method = selected.attribute("method", "default");
    settingsWidget->chkEnabled->setChecked(selected.attribute("enabled").toInt());
    if (method == "default") {
        settingsWidget->radDefault->setChecked(true);
    } else if (method == "center") {
        settingsWidget->radCenter->setChecked(true);
    } else if (method == "tile") {
        settingsWidget->radTile->setChecked(true);
    } else if (method == "str") {
        settingsWidget->radStretchLeave->setChecked(true);
    } else if (method == "ir") {
        settingsWidget->radStretchIgnore->setChecked(true);
    } else if (method == "etr") {
        settingsWidget->radStretchCrop->setChecked(true);
    }
}

void ImageWindow::enableToggled() {
    selected.setAttribute("enabled", settingsWidget->chkEnabled->isChecked());
    listBox->getSelected()->setImageEnabled(selected.attribute("enabled").toInt());
}

void ImageWindow::radioBtnClicked() {
    if (settingsWidget->radDefault->isChecked()) {
        selected.removeAttribute("method");
    } else if (settingsWidget->radCenter->isChecked()) {
        selected.setAttribute("method", "center");
    } else if (settingsWidget->radStretchLeave->isChecked()) {
        selected.setAttribute("method", "str");
    } else if (settingsWidget->radStretchIgnore->isChecked()) {
        selected.setAttribute("method", "ir");
    } else if (settingsWidget->radStretchCrop->isChecked()) {
        selected.setAttribute("method", "etr");
    } else if (settingsWidget->radTile->isChecked()) {
        selected.setAttribute("method", "tile");
    }
}

